﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace Gmantis.Controls
{
    internal class RangeSelectionManager
    {
        // Fields
        private bool _isProcessing;
        private int _rangeSelectedItem;

        // Events
        public event EventHandler<SelectionChangedEventArgs<int>> SelectionChanged;

        public event EventHandler<SelectionChangedEventArgs<int>> SelectionChanging;

        // Methods
        public RangeSelectionManager()
        {
            this.SelectionMode = Controls.SelectionMode.Single;
            this.SelectedItems = new OrderedSet();
        }

        public void ClearSelection()
        {
            OrderedSet removedItems = new OrderedSet(this.SelectedItems);
            OrderedSet addedItems = new OrderedSet();
            this.SelectedItem = null;
            this.OnSelectionChanging(addedItems, removedItems);
            this.PerformSelection(addedItems, removedItems);
        }

        internal bool Contains(int index)
        {
            return this.SelectedItems.Contains(index);
        }

        private void HandleConsecutiveSelection(int index)
        {
            Range<int> range = (this._rangeSelectedItem < index) ? new Range<int>(this._rangeSelectedItem, index) : new Range<int>(index, this._rangeSelectedItem);
            if (this.SelectedItems.Count == 1)
            {
                int num = this.SelectedItems[0];
                if (num.Equals(index))
                {
                    return;
                }
            }
            OrderedSet removedItems = new OrderedSet(this.SelectedItems);
            OrderedSet addedItems = new OrderedSet { range };
            this.SelectedItem = new int?(index);
            this.OnSelectionChanging(addedItems, removedItems);
            this.PerformSelection(addedItems, removedItems);
        }

        private void HandleExtendedSelection(int index, bool isSelected)
        {
            if (KeyboardUtil.Ctrl && KeyboardUtil.Shift)
            {
                this.HandleMultipleRangeSelection(index);
            }
            else if (KeyboardUtil.Ctrl)
            {
                this.HandleNonConsecutiveSelection(index);
            }
            else if (KeyboardUtil.Shift)
            {
                this.HandleConsecutiveSelection(index);
            }
            else
            {
                this.HandleSingleSelection(index, isSelected);
            }
        }

        private void HandleMultipleRangeSelection(int index)
        {
            OrderedSet removedItems = new OrderedSet();
            OrderedSet addedItems = new OrderedSet();
            Range<int> range = new Range<int>(index, index);
            if (this.SelectedItem.HasValue)
            {
                int? selectedItem = this.SelectedItem;
                int num = index;
                range = ((selectedItem.GetValueOrDefault() < num) && selectedItem.HasValue) ? new Range<int>(this.SelectedItem.Value, index) : new Range<int>(index, this.SelectedItem.Value);
            }
            if (this.SelectedItem.HasValue && (this.SelectedItem.Value != index))
            {
                addedItems.Add(range);
                this._rangeSelectedItem = index;
            }
            this.OnSelectionChanging(addedItems, removedItems);
            this.PerformSelection(addedItems, removedItems);
        }

        private void HandleMultipleSelection(int index, bool isSelected)
        {
            if (isSelected)
            {
                if (!this.SelectedItems.Contains(index))
                {
                    OrderedSet removedItems = new OrderedSet();
                    OrderedSet addedItems = new OrderedSet {
                    new Range<int>(index, index)
                };
                    this.SelectedItem = new int?(this._rangeSelectedItem = index);
                    this.OnSelectionChanging(addedItems, removedItems);
                    this.PerformSelection(addedItems, removedItems);
                }
            }
            else if (this.SelectedItems.Contains(index))
            {
                OrderedSet set4 = new OrderedSet {
                new Range<int>(index, index)
            };
                OrderedSet set5 = new OrderedSet();
                this.SelectedItem = null;
                this.OnSelectionChanging(set5, set4);
                this.PerformSelection(set5, set4);
            }
        }

        private void HandleMultipleSelectionTest(int index, bool ctl, bool shift)
        {
            if (ctl && shift)
            {
                this.HandleMultipleRangeSelection(index);
            }
            else if (ctl)
            {
                this.HandleNonConsecutiveSelection(index);
            }
            else if (shift)
            {
                this.HandleConsecutiveSelection(index);
            }
        }

        private void HandleNonConsecutiveSelection(int index)
        {
            OrderedSet removedItems = new OrderedSet();
            OrderedSet addedItems = new OrderedSet();
            Range<int> range = new Range<int>(index, index);
            if (this.SelectedItems.Contains(index))
            {
                removedItems.Add(range);
            }
            else
            {
                addedItems.Add(range);
                this.SelectedItem = new int?(index);
                this._rangeSelectedItem = this.SelectedItem.Value;
            }
            this.OnSelectionChanging(addedItems, removedItems);
            this.PerformSelection(addedItems, removedItems);
        }

        public void HandleSelectionChange(int index, bool isSelected)
        {
            if (!this._isProcessing)
            {
                this._isProcessing = true;
                switch (this.SelectionMode)
                {
                    case SelectionMode.Single:
                        this.HandleSingleSelection(index, isSelected);
                        break;

                    case SelectionMode.Multiple:
                        this.HandleNonConsecutiveSelection(index);
                        break;

                    case SelectionMode.Extended:
                        this.HandleExtendedSelection(index, isSelected);
                        break;
                }
                this._isProcessing = false;
            }
        }

        internal void HandleSelectionChangeTest(int index, bool ctl, bool shift)
        {
            if (!this._isProcessing)
            {
                this._isProcessing = true;
                switch (this.SelectionMode)
                {
                    case SelectionMode.Multiple:
                        this.HandleMultipleSelectionTest(index, ctl, shift);
                        break;
                }
                this._isProcessing = false;
            }
        }

        private void HandleSingleSelection(int index, bool isSelected)
        {
            if (isSelected)
            {
                if (this.SelectedItems.Count == 1)
                {
                    int num = this.SelectedItems[0];
                    if (num.Equals(index))
                    {
                        return;
                    }
                }
                OrderedSet removedItems = new OrderedSet(this.SelectedItems);
                OrderedSet addedItems = new OrderedSet { new Range<int>(index, index) };
                this.SelectedItem = new int?(this._rangeSelectedItem = index);
                this.OnSelectionChanging(addedItems, removedItems);
                this.PerformSelection(addedItems, removedItems);
            }
            else
            {
                if (this.SelectedItems.Count <= 0)
                {
                    int num3 = this.SelectedItems[0];
                    if (!num3.Equals(index))
                    {
                        return;
                    }
                }
                OrderedSet set4 = new OrderedSet(this.SelectedItems);
                OrderedSet set5 = new OrderedSet();
                this.SelectedItem = null;
                this.OnSelectionChanging(set5, set4);
                this.PerformSelection(set5, set4);
            }
        }

        private void OnSelectionChanged(OrderedSet addedItems, OrderedSet removedItems)
        {
            if (((addedItems.Count > 0) || (removedItems.Count > 0)) && (this.SelectionChanged != null))
            {
                SelectionChangedEventArgs<int> e = new SelectionChangedEventArgs<int>(addedItems, removedItems);
                this.SelectionChanged(this, e);
            }
        }

        private void OnSelectionChanging(OrderedSet addedItems, OrderedSet removedItems)
        {
            if (((addedItems.Count > 0) || (removedItems.Count > 0)) && (this.SelectionChanging != null))
            {
                SelectionChangedEventArgs<int> e = new SelectionChangedEventArgs<int>(addedItems, removedItems);
                this.SelectionChanging(this, e);
            }
        }

        private void PerformSelection(OrderedSet addedItems, OrderedSet removedItems)
        {
            if ((addedItems.Count > 0) || (removedItems.Count > 0))
            {
                this.SelectedItems.Remove(removedItems);
                this.SelectedItems.Add(addedItems);
                if (this.SelectedItems.Count == 0)
                {
                    this.SelectedItem = null;
                }
                this.OnSelectionChanged(addedItems, removedItems);
            }
        }

        internal void Shift(int index)
        {
            this.SelectedItems.Shift(index, index);
        }

        internal void Shrink(int index)
        {
            this.SelectedItems.Shrink(index, index);
        }

        // Properties
        public int? SelectedItem { get; private set; }

        public OrderedSet SelectedItems { get; private set; }

        public SelectionMode SelectionMode { get; set; }
    }
}
